package com.crawler.clent;

import java.util.List;
import java.util.Map;

import org.apache.commons.codec.binary.Base64;
import org.apache.http.Header;
import org.apache.http.NameValuePair;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import com.core.entity.Condition;
import com.core.utils.ConditionDb;
import com.crawler.entity.Account;
import com.crawler.entity.Order;
import com.crawler.pojo.Constant;
import com.crawler.pojo.CrawlerSeed;
import com.crawler.pojo.Operate;
import com.crawler.pojo.PageType;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jfinal.kit.StrKit;

public class A12306Crawler extends CrawlerAdapter {
	
	public A12306Crawler() {
		if(getClient() == null){
			try {
				initClient(null);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	public Map<String, Object> start(CrawlerSeed crawlerSeed) {
		Map<String,Object> map = Maps.newHashMap();
		switch (crawlerSeed.getOp()) {
			case login:
				map = login(crawlerSeed);
				break;
			case fetch:
				map = fetch(crawlerSeed);
				break;
			case destory:
				stop(crawlerSeed);
				break;
			default:
				map = login(crawlerSeed);
				break;
			}
		return map;
	}
	
	public static final String Host = "kyfw.12306.cn";

	private Map<String, Object> login(CrawlerSeed crawlerSeed) {
		
		setLoginName(crawlerSeed.getUsername());
		setPassword(crawlerSeed.getPassword());
		setPageTypeLoginName(getLoginName());
		
		Map<String,Object> map = Maps.newHashMap();
		if(crawlerSeed.getCheckCode() == null){
			logout();//降低第三方登陆错误
			//获取验证码
			HttpPost httpPost = new HttpPost(PageType.PAGE_CHECKCODE.getUrl());
			httpPost.setHeaders(getCheckCodeHeaders().toArray(new Header[0]));
			byte[] b = getByteArray(requestProcessor(getClient(), httpPost),httpPost.getURI().toString());
			String imgBase64 = Base64.encodeBase64String(b);
			map.put(Constant.OPERATE, Operate.needCheckCode.getValue());
			map.put(Constant.checkCodeImg, imgBase64);
		}else{
			String token = crawlerSeed.getToken();
			String checkCode = crawlerSeed.getCheckCode();
			if(StrKit.isBlank(token)){
				List<NameValuePair> params = Lists.newArrayList();
				params.add(new BasicNameValuePair("rand", "sjrand"));
				params.add(new BasicNameValuePair("randCode", checkCode.substring(1, checkCode.length())));
				String validate = requestPost(PageType.PAGE_CHECKCODEANSYN.getUrl(), params, getCommonHeaders());
//				{"validateMessagesShowId":"_validatorMessage","status":true,"httpstatus":200,"data":{"result":"1","msg":"TRUE"},"messages":[],"validateMessages":{}}
				if(validate.contains("TRUE")){//验证码通过
					getToken(map,getCommonHeaders());
				}else{
					map.put(Constant.ERROR, "验证码错误");
					CrawlerManager.remove(getLoginName());
				}
			}else{
				String[] tokenArr = token.split(":::")[0].split(",-,");
				String token_key = tokenArr[0];
				String token_value = tokenArr[1];
				List<NameValuePair> params = Lists.newArrayList();
				params.add(new BasicNameValuePair("loginUserDTO.user_name", crawlerSeed.getUsername()));
				params.add(new BasicNameValuePair("myversion", "undefined"));
				params.add(new BasicNameValuePair("userDTO.password", crawlerSeed.getPassword()));
				params.add(new BasicNameValuePair("randCode", checkCode.substring(1, checkCode.length())));
				params.add(new BasicNameValuePair(token_key, token_value));
				String html = requestPost(PageType.PAGE_LOGIN.getUrl(), params, getCommonHeaders());
//				{"validateMessagesShowId":"_validatorMessage","status":false,"httpstatus":200,"messages":["网络繁忙，请您重试。如正在使用第三方购票软件或插件，请卸载后重试。"],"validateMessages":{}}
//				{"validateMessagesShowId":"_validatorMessage","status":true,"httpstatus":200,"data":{"loginCheck":"Y"},"messages":[],"validateMessages":{}}
//				{"validateMessagesShowId":"_validatorMessage","status":true,"httpstatus":200,"data":{},"messages":["验证码不正确！"],"validateMessages":{}}
				if(html.contains("Y")){
					map.put(Constant.OPERATE, Operate.fetch.getValue());
					setLoginName(crawlerSeed.getUsername());
					setPassword(crawlerSeed.getPassword());
				}else{
					map.put(Constant.ERROR, html.substring(html.indexOf("["), html.indexOf("]")));
					CrawlerManager.remove(getLoginName());
				}
			}
		}
		return map;
	}

	/**
	 * 请求头 
	 */
	private List<Header> getCommonHeaders() {
		List<Header> headers = Lists.newArrayList();
		headers.add(new BasicHeader("Accept", "	*/*"));
		headers.add(new BasicHeader("Host", Host));
		headers.add(new BasicHeader("Referer", PageType.PAGE_TOKEN.getUrl()));
		headers.add(new BasicHeader("DNT", "1"));
		headers.add(new BasicHeader("X-Requested-With", "XMLHttpRequest"));
		headers.add(new BasicHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"));
		headers.add(new BasicHeader("Connection", "keep-alive"));
		headers.add(new BasicHeader("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3"));
		headers.add(new BasicHeader("Accept-Encoding", "gzip, deflate"));
		headers.add(new BasicHeader("Cache-Control", "no-cache"));
		headers.add(new BasicHeader("Pragma", "no-cache"));
		return headers;
	}
	
	/**
	 * 请求头 图片验证码
	 */
	private List<Header> getCheckCodeHeaders() {
		List<Header> headers = Lists.newArrayList();
		headers.add(new BasicHeader("Host", Host));
		headers.add(new BasicHeader("Referer", PageType.PAGE_TOKEN.getUrl()));
		headers.add(new BasicHeader("DNT", "1"));
		headers.add(new BasicHeader("Accept", "image/png,image/*;q=0.8,*/*;q=0.5"));
		headers.add(new BasicHeader("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3"));
		headers.add(new BasicHeader("Accept-Encoding", "gzip, deflate"));
		headers.add(new BasicHeader("Connection", "keep-alive"));
		return headers;
	}
	
	/**
	 * 获取登陆的Token
	 */
	private void getToken(Map<String, Object> map,List<Header> headers) {
		String init = requestGet(PageType.PAGE_TOKEN.getUrl(),headers);
		Document doc = Jsoup.parse(init);
		String js_url = doc.getElementsByTag("script").get(2).attr("src");
		String js = requestGet("https://kyfw.12306.cn"+js_url,headers);
		map.put("js", js);
		map.put("token", true);
	}

	private void setPageTypeLoginName(String loginName) {
		for (PageType type : PageType.values()) {
			type.setLoginName(getLoginName());
		}
	}

	private Map<String, Object> fetch(CrawlerSeed crawlerSeed) {
		Map<String,Object> map = Maps.newHashMap();
		String userInfoPage = requestGet(PageType.PAGE_USERINFO.getUrl(), null);
		Document doc = Jsoup.parse(userInfoPage);
//		基本信息
		Elements elements = doc.getElementById("basic_info_view").getElementsByClass("con");
		for (Element element : elements) {
			System.err.println(element.text());
		}
//		联系方式
		elements = doc.getElementById("relation_way_view").getElementsByClass("con");
		for (Element element : elements) {
			System.err.println(element.text());
		}
//		附加信息 基本
		elements = doc.getElementById("append_info_base").getElementsByClass("con");
		for (Element element : elements) {
			System.err.println(element.text());
		}
//		附加信息
		elements = doc.getElementById("append_info_view").getElementsByClass("con");
		for (Element element : elements) {
			System.err.println(element.text());
		}
		
		String contactPage = requestGet(PageType.PAGE_CONTACT.getUrl(), null);
		
		String orderPage = requestGet(PageType.PAGE_ORDER.getUrl(), null);
		
		String _orderPage = requestGet(PageType.PAGE_ORDER_NOCOMPLETE.getUrl(), null);
		
//		//订单分页
//		List<String> orderPages = Lists.newArrayList();
//		String firstPage = requestPost(PageType.PAGE_ORDER.getUrl(), null, null);
//		orderPages.add(firstPage);
//		String nextPageUrl = ParserKit.parseText(PageType.PAGE_ORDER, firstPage);
//		String nextPage = null;
//		while (true) {
//			if(StrKit.notBlank(nextPageUrl)){
//				nextPage = requestPost(nextPageUrl, null, null);
//				nextPageUrl = ParserKit.parseText(PageType.PAGE_ORDER, nextPage);
//				orderPages.add(nextPage);
//			}else{
//				break;
//			}
//		}
//		
//		//解析用户信息
//		String userInfoHtml = requestGet(PageType.PAGE_USERINFO.getUrl(), null);
//		Map<String,Object> userInfo = ParserKit.parseMap(PageType.PAGE_USERINFO, userInfoHtml);
//		userInfo.put("loginName", getLoginName());
//		
//		//解析订单
//		List<Map<String,Object>> orderList = Lists.newArrayList();
//		for (String orderPage : orderPages) {
//			orderList.addAll(ParserKit.parseListMap(PageType.PAGE_ORDER, orderPage));
//		}
//		
//		//解析订单收货地址 & 封装完整的订单
//		List<Map<String,Object>> orderDetialList = Lists.newArrayList();
//		for (Map<String, Object> orderMap : orderList) {
//			String addressHtml = requestGet(orderMap.get("orderAddress").toString(), null);
//			String orderAddress = ParserKit.parseText(PageType.PAGE_ORDERDETIAL,orderMap.get("orderStatus").toString(), addressHtml);
//			orderMap.put("orderAddress", orderAddress);
//			orderMap.put("loginName", getLoginName());
//			orderMap.put("customerID", userInfo.get("customerID"));
//			orderDetialList.add(orderMap);
//		}
//	
//		//清空同一个customerID的数据
//		clearDataByCustomerID(userInfo.get("customerID").toString().trim());
//		
//		//保存数据
//		ModelDb.save(JdAccount.class, userInfo);
//		ModelDb.batchSave(JdOrder.class, orderDetialList);		
//	
//		//登出
		logout();
		map.put(Constant.OPERATE, getLoginName()+"抓取完成！");
		CrawlerManager.remove(getLoginName());
		return map;
	}

	private void clearDataByCustomerID(String customerID) {
		Condition condition = Condition.parseCondition("customerID_string_eq");
		condition.setValue(customerID);
		ConditionDb.delete(Account.class, condition);
		ConditionDb.delete(Order.class, condition);
	}

	private void logout() {
		requestGet(PageType.PAGE_LOGOUT.getUrl(), null);
	}

	@Override
	public Map<String, Object> stop(CrawlerSeed crawlerSeed) {
		logout();
		CrawlerManager.remove(crawlerSeed.getUsername());
		return null;
	}

}
